package org.stvd.core.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipCompressor {
    static final int BUFFER = 8192;

    private File zipFile;
    private Boolean isRecursive = true;
    private String fileRegEx = "";

    public ZipCompressor() {
    }

    public ZipCompressor(String pathName) {
        zipFile = new File(pathName);
    }

    public ZipCompressor(Boolean isRecursive, String fileRegEx) {
        this.isRecursive = isRecursive;
        this.fileRegEx = fileRegEx;
    }

    public ZipCompressor(String pathName, Boolean isRecursive) {
        zipFile = new File(pathName);
        this.isRecursive = isRecursive;
    }

    public ZipCompressor(String pathName, String fileRegEx) {
        zipFile = new File(pathName);
        this.fileRegEx = fileRegEx;
    }

    public ZipCompressor(String pathName, Boolean isRecursive, String fileRegEx) {
        zipFile = new File(pathName);
        this.isRecursive = isRecursive;
        this.fileRegEx = fileRegEx;
    }

    private void compress(File file, ZipOutputStream out, String basedir) {
        /* 判断是目录还是文件 */
        if (file.isDirectory()) {
            if (this.isRecursive) {
                // System.out.println("压缩：" + basedir + file.getName());
                this.compressDirectory(file, out, basedir);
            }
        } else {
            // System.out.println("压缩：" + basedir + file.getName());
            this.compressFile(file, out, basedir);
        }
    }

    public void compress(String... pathName) {
        FileOutputStream fileOutputStream = null;
        CheckedOutputStream cos = null;
        ZipOutputStream out = null;
        try {
            fileOutputStream = new FileOutputStream(zipFile);
            cos = new CheckedOutputStream(fileOutputStream, new CRC32());
            out = new ZipOutputStream(cos);
            String basedir = "";
            for (int i = 0; i < pathName.length; i++) {
                compress(new File(pathName[i]), out, basedir);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (cos != null) {
                    cos.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
            }
        }

    }

    public void compress(String srcPathName) {
        File file = new File(srcPathName);
        if (!file.exists())
            throw new RuntimeException(srcPathName + "不存在！");
        FileOutputStream fileOutputStream = null;
        CheckedOutputStream cos = null;
        ZipOutputStream out = null;
        try {
            fileOutputStream = new FileOutputStream(zipFile);
            cos = new CheckedOutputStream(fileOutputStream, new CRC32());
            out = new ZipOutputStream(cos);
            String basedir = "";
            if (this.isRecursive) {
                compress(file, out, basedir);
            } else {
                compressDirectory(file, out, basedir);
            }
            out.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (cos != null) {
                    cos.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
            }
        }
    }

    /** 压缩一个目录 */
    private void compressDirectory(File dir, ZipOutputStream out, String basedir) {
        if (!dir.exists())
            return;

        File[] files = dir.listFiles();
        if (files != null && files.length > 0) {
            for (int i = 0; i < files.length; i++) {
                /* 递归 */
                compress(files[i], out, basedir + dir.getName() + "/");
            }
        }
    }

    /** 压缩一个文件 */
    private void compressFile(File file, ZipOutputStream out, String basedir) {
        if (!file.exists()) {
            return;
        }
        boolean bCompress = true;
        if (!"".equals(this.fileRegEx)) {
            Pattern pattern = Pattern.compile(this.fileRegEx);
            // 忽略大小写的写法
            // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
            Matcher matcher = pattern.matcher(file.getName());
            // 字符串是否与正则表达式相匹配
            bCompress = matcher.matches();
        }
        if (bCompress) {
            BufferedInputStream bis = null;
            try {
                System.out.println("压缩文件：" + basedir + file.getName());

                bis = new BufferedInputStream(new FileInputStream(file));
                ZipEntry entry = new ZipEntry(basedir + file.getName());
                out.putNextEntry(entry);
                byte data[] = new byte[BUFFER];
                int count = bis.read(data, 0, BUFFER);
                while (count != -1) {
                    out.write(data, 0, count);
                    count = bis.read(data, 0, BUFFER);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    if (bis != null) {
                        bis.close();
                    }
                } catch (IOException e) {
                }
            }
        }
    }

    // public static void main(String[] args) {
    // ZipCompressor zc = new ZipCompressor("D:/demo.zip", true,"");
    //// "^.*\\.(xml|txt)$");
    // zc.compress("D:\\demo");//
    //// ,"E:/resource/css","E:/resource/images");
    // }
}